home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / editors / emacs / xemacs / xemacs-1.006 / xemacs-1 / lib / xemacs-19.13 / lisp / modes / c-comment.el < prev    next >
Encoding:
Text File  |  1995-04-17  |  10.3 KB  |  300 lines

  1. ;;; c-comment.el --- edit C comments
  2.  
  3. ;; Keywords: c
  4.  
  5. ;;; Copyright (C) 1987, 1988, 1989 Kyle E. Jones
  6. ;;;
  7. ;;; Verbatim copies of this file may be freely redistributed.
  8. ;;;
  9. ;;; Modified versions of this file may be redistributed provided that this
  10. ;;; notice remains unchanged, the file contains prominent notice of
  11. ;;; author and time of modifications, and redistribution of the file
  12. ;;; is not further restricted in any way.
  13. ;;;
  14. ;;; This file is distributed `as is', without warranties of any kind.
  15.  
  16. (provide 'c-comment-edit)
  17.  
  18. (defvar c-comment-leader " *"
  19.   "*Leader used when rebuilding edited C comments.  The value of this variable
  20. should be a two-character string.  Values of "  ", " *" and "**" produce the
  21. comment styles:
  22.     /*    /*    /*
  23.       ...     * ...    ** ...
  24.       ...     * ...    ** ...
  25.     */     */    */
  26. respectively.")
  27.  
  28. (defconst c-comment-leader-regexp "^[     ]*\\(\\*\\*\\|\\*\\)?[ ]?"
  29.   "Regexp used to match C comment leaders.")
  30.  
  31. (defvar c-comment-edit-mode 'text-mode
  32.   "*Major mode used by `c-comment-edit' when editing C comments.")
  33.  
  34. (defvar c-comment-edit-hook nil
  35.   "*Function to call whenever `c-comment-edit' is used.
  36. The function is called just before the `c-comment-edit' function allows you to
  37. begin editing the comment.")
  38.  
  39. (defvar c-comment-edit-buffer-alist nil
  40.   "Assoc list of C buffers and their associated comment buffers.
  41. Elements are of the form (C-BUFFER COMMENT-BUFFER COMMENT-START COMMENT-END)
  42. COMMENT-START and COMMENT-END are markers in the C-BUFFER.")
  43.  
  44. (defmacro save-point (&rest body)
  45.   "Save value of point, evalutes FORMS and restore value of point.
  46. If the saved value of point is no longer valid go to (point-max).
  47. The variable `save-point' is lambda-bound to the value of point for
  48. the duration of this call."
  49.   (list 'let '((save-point (point)))
  50.     (list 'unwind-protect
  51.           (cons 'progn body)
  52.           '(goto-char (min (point-max) save-point)))))
  53.  
  54. (defmacro marker (pos &optional buffer)
  55.   (list 'set-marker '(make-marker) pos buffer))
  56.  
  57.  
  58. ;;;### autoload
  59. (defun c-comment-edit (search-prefix)
  60.   "Edit multi-line C comments.
  61. This command allows the easy editing of a multi-line C comment like this:
  62.    /*
  63.     * ...
  64.     * ...
  65.     */
  66. The comment may be indented or flush with the left margin.
  67.  
  68. If point is within a comment, that comment is used.  Otherwise the
  69. comment to be edited is found by searching forward from point.
  70.  
  71. With one \\[universal-argument] searching starts after moving back one
  72.   paragraph.
  73. With two \\[universal-argument]'s searching starts at the beginning of the
  74.   current or proceeding C function.
  75. With three \\[universal-argument]'s searching starts at the beginning of the
  76.   current page.
  77. With four \\[universal-argument]'s searching starts at the beginning of the
  78.   current buffer (clipping restrictions apply).
  79.  
  80. Once located, the comment is copied into a temporary buffer, the comment
  81. leaders and delimiters are stripped away and the resulting buffer is
  82. selected for editing.  The major mode of this buffer is controlled by
  83. the variable `c-comment-edit-mode'.
  84.  
  85. Use \\[c-comment-edit-end] when you have finished editing the comment.  The
  86. comment will be inserted into the original buffer with the appropriate
  87. delimiters and indention, replacing the old version of the comment.  If
  88. you don't want your edited version of the comment to replace the
  89. original, use \\[c-comment-edit-abort]." 
  90.   (interactive "*P")
  91.   (let ((c-buffer (current-buffer))
  92.     marker tem c-comment-fill-column c-comment-buffer
  93.     c-comment-start c-comment-end
  94.     (inhibit-quit t))
  95.     ;; honor search-prefix
  96.     (cond ((equal search-prefix '(4))
  97.        (backward-paragraph))
  98.       ((equal search-prefix '(16))
  99.        (end-of-defun)
  100.        (beginning-of-defun)
  101.        (backward-paragraph))
  102.       ((equal search-prefix '(64))
  103.        (backward-page))
  104.       ((equal search-prefix '(256))
  105.        (goto-char (point-min))))
  106.     (if (and (null search-prefix) (setq tem (within-c-comment-p)))
  107.     (setq c-comment-start (marker (car tem))
  108.           c-comment-end (marker (cdr tem)))
  109.       (let (start end)
  110.     (condition-case error-data
  111.         (save-point
  112.           (search-forward "/*")
  113.           (setq start (- (point) 2))
  114.           (search-forward "*/")
  115.           (setq end (point)))
  116.       (search-failed (error "No C comment found.")))
  117.     (setq c-comment-start (marker start))
  118.     (setq c-comment-end (marker end))))
  119.     ;; calculate the correct fill-column for the comment
  120.     (setq c-comment-fill-column (- fill-column
  121.                    (save-excursion
  122.                      (goto-char c-comment-start)
  123.                      (current-column))))
  124.     ;; create the comment buffer
  125.     (setq c-comment-buffer
  126.       (generate-new-buffer (concat (buffer-name) " *C Comment Edit*")))
  127.     ;; link into the c-comment-edit-buffer-alist
  128.     (setq c-comment-edit-buffer-alist
  129.       (cons (list (current-buffer) c-comment-buffer
  130.               c-comment-start c-comment-end)
  131.         c-comment-edit-buffer-alist))
  132.     ;; copy to the comment to the comment-edit buffer
  133.     (copy-to-buffer c-comment-buffer (+ c-comment-start 2) (- c-comment-end 2))
  134.     ;; mark the position of point, relative to the beginning of the
  135.     ;; comment, in the comment buffer.  (iff point is within a comment.)
  136.     (or search-prefix (< (point) c-comment-start)
  137.     (setq marker (marker (+ (- (point) c-comment-start 2) 1)
  138.                  c-comment-buffer)))
  139.     ;; select the comment buffer for editing
  140.     (switch-to-buffer c-comment-buffer)
  141.     ;; remove the comment leaders and delimiters
  142.     (goto-char (point-min))
  143.     (while (not (eobp))
  144.       (and (re-search-forward c-comment-leader-regexp nil t)
  145.        (replace-match "" nil t))
  146.       (forward-line))
  147.     ;; run appropriate major mode
  148.     (funcall (or c-comment-edit-mode 'fundamental-mode))
  149.     ;; override user's default fill-column here since it will lose if
  150.     ;; the comment is indented in the C buffer.
  151.     (setq fill-column c-comment-fill-column)
  152.     ;; delete one leading whitespace char
  153.     (goto-char (point-min))
  154.     (if (looking-at "[ \n\t]")
  155.     (delete-char 1))
  156.     ;; restore cursor if possible
  157.     (goto-char (or marker (point-min)))
  158.     (set-buffer-modified-p nil))
  159.   ;; run user hook, if present.
  160.   (if c-comment-edit-hook
  161.       (funcall c-comment-edit-hook))
  162.   ;; final admonition
  163.   (message
  164.    (substitute-command-keys
  165.     "Type \\[c-comment-edit-end] to end edit, \\[c-comment-edit-abort] to abort with no change.")))
  166.  
  167. (defun c-comment-edit-end ()
  168.   "End c-comment-edit.
  169. C comment is replaced by its edited counterpart in the appropriate C buffer.
  170. Indentation will be the same as the original."
  171.   (interactive)
  172.   (let ((tuple (find-c-comment-buffer)))
  173.     (if (null tuple)
  174.     (error "Not a c-comment-edit buffer."))
  175.     (let ((inhibit-quit t)
  176.       (c-comment-c-buffer (car tuple))
  177.       (c-comment-buffer (nth 1 tuple))
  178.       (c-comment-start (nth 2 tuple))
  179.       (c-comment-end (nth 3 tuple)))
  180.       (cond
  181.        ((buffer-modified-p)
  182.     ;; rebuild the comment
  183.     (goto-char (point-min))
  184.     (insert "/*\n")
  185.     (if (string= c-comment-leader "  ")
  186.         (while (not (eobp))
  187.           (if (not (eolp))
  188.           (insert c-comment-leader " "))
  189.           (forward-line))
  190.       (while (not (eobp))
  191.         (insert c-comment-leader (if (eolp) "" " "))
  192.         (forward-line)))
  193.     (if (not (char-equal (preceding-char) ?\n))
  194.         (insert "\n"))
  195.     (insert (if (string= c-comment-leader " *") " */" "*/"))
  196.     ;; indent if necessary
  197.     (let ((indention
  198.            (save-excursion
  199.          (set-buffer c-comment-c-buffer)
  200.          (goto-char c-comment-start)
  201.          (current-column))))
  202.       (goto-char (point-min))
  203.       (cond ((not (zerop indention))
  204.          ;; first line is already indented
  205.          ;; in the C buffer
  206.          (forward-line)
  207.          (while (not (eobp))
  208.            (indent-to indention)
  209.            (forward-line)))))
  210.     ;; replace the old comment with the new
  211.     (save-excursion
  212.       (set-buffer c-comment-c-buffer)
  213.       (save-point
  214.         (save-excursion
  215.           (delete-region c-comment-start c-comment-end)
  216.           (goto-char c-comment-start)
  217.           (set-buffer c-comment-buffer)
  218.           (append-to-buffer c-comment-c-buffer
  219.                 (point-min) (point-max))))))
  220.        (t (message "No change.")))
  221.       ;; switch to the C buffer
  222.       (if (get-buffer-window c-comment-c-buffer)
  223.       (select-window (get-buffer-window c-comment-c-buffer))
  224.     (switch-to-buffer c-comment-c-buffer))
  225.       ;; delete the window viewing the comment buffer
  226.       (and (get-buffer-window c-comment-buffer)
  227.        (delete-window (get-buffer-window c-comment-buffer)))
  228.       ;; unlink the tuple from c-comment-edit-buffer-alist
  229.       (setq c-comment-edit-buffer-alist
  230.         (delq tuple c-comment-edit-buffer-alist))
  231.       ;; let Emacs reclaim various resources
  232.       (save-excursion
  233.     (set-buffer c-comment-buffer)
  234.     (set-buffer-modified-p nil)
  235.     (kill-buffer c-comment-buffer))
  236.       (set-marker c-comment-start nil)
  237.       (set-marker c-comment-end nil))))
  238.  
  239. (defun c-comment-edit-abort ()
  240.   "Abort a c-comment-edit with no change."
  241.   (interactive)
  242.   (let* ((tuple (find-c-comment-buffer))
  243.      (c-comment-c-buffer (car tuple))
  244.      (c-comment-buffer (nth 1 tuple))
  245.      (c-comment-start (nth 2 tuple))
  246.      (c-comment-end (nth 3 tuple)))
  247.     (if (null tuple)
  248.     (error "Not a c-comment-edit buffer."))
  249.     ;; switch to the C buffer
  250.     (if (get-buffer-window c-comment-c-buffer)
  251.     (select-window (get-buffer-window c-comment-c-buffer))
  252.       (switch-to-buffer c-comment-c-buffer))
  253.     (let ((inhibit-quit t))
  254.       (save-excursion
  255.     (set-buffer c-comment-buffer)
  256.     (set-buffer-modified-p nil)
  257.     (kill-buffer c-comment-buffer))
  258.       ;; unlink the tuple from c-comment-edit-buffer-alist
  259.       (setq c-comment-edit-buffer-alist
  260.         (delq tuple c-comment-edit-buffer-alist))
  261.       (set-marker c-comment-start nil)
  262.       (set-marker c-comment-end nil)
  263.       (message "Aborted with no change."))))
  264.  
  265. ;; this loses on /* /* */ but doing it right would be grim.
  266. (defun within-c-comment-p ()
  267.   (condition-case error-data
  268.       (let (start end)
  269.     (save-point
  270.       (search-backward "/*")
  271.       (setq start (point))
  272.       (search-forward "*/")
  273.       (setq end (point)))
  274.     (if (< (point) end) (cons start end) nil))
  275.     (search-failed nil)))
  276.  
  277. (defun find-c-comment-buffer (&optional buffer)
  278.   (or buffer (setq buffer (current-buffer)))
  279.   (let ((list c-comment-edit-buffer-alist))
  280.     (catch 'return-value
  281.       (while list
  282.     (if (eq (nth 1 (car list)) buffer)
  283.         (throw 'return-value (car list))
  284.       (setq list (cdr list)))))))
  285.         
  286. (defun find-c-comment-c-buffer (&optional buffer)
  287.   (or buffer (setq buffer (current-buffer)))
  288.   (let ((list c-comment-edit-buffer-alist))
  289.     (catch 'return-value
  290.       (while list
  291.     (if (eq (car (car list)) buffer)
  292.         (throw 'return-value (car list))
  293.       (setq list (cdr list)))))))
  294.  
  295. ;; keys;
  296. (define-key mode-specific-map "\e" 'c-comment-edit-end)
  297. (define-key mode-specific-map "\C-]" 'c-comment-edit-abort)
  298.  
  299.  
  300.